Graphics processing systems are used to process graphics data in order to render images. As part of the processing performed by a graphics processing system, primitives of objects in a three-dimensional scene are processed to determine which of the primitives are visible at each sample position of a rendering space of the graphics processing system, and to determine the appearance of the visible primitives at the sample positions. In some examples, a single sample position may correspond to a pixel position of the final rendered image, but in other examples, more than one (e.g. four) sample positions may correspond to each pixel position. Two stages of a typical graphics processing system are: (i) hidden surface removal (HSR), in which surfaces which are hidden by other surfaces in a scene are removed, and (ii) texturing and/or shading in which a surface of an object is given a suitable appearance. In a deferred rendering graphics processing system the hidden surface removal stage is implemented before the texturing/shading stage.
An example of part of a deferred rendering graphics processing system 100 is shown in FIG. 1. The system 100 comprises a graphics processing unit (GPU) 102 comprising a HSR module 104, and a fragment processing module 106 for performing texturing and/or shading on fragments of primitives. As a matter of terminology, a “fragment” is an element of a primitive at a sample position. The system 100 also comprises a memory 108 which is arranged to provide primitives to the GPU 102 and to receive processed pixels from the GPU 102. The HSR module 104 comprises depth testing logic 110, a depth buffer 112 and a tag buffer 114. In the deferred rendering system 100, the HSR module 104 is arranged to receive the primitives from the memory 108. The depth buffer 112 stores depth values for an array of sample positions to indicate the current depth at each sample position. The depth testing logic 110 uses the depth values stored in the depth buffer 112 to perform depth tests for incoming fragments to determine if the fragments are hidden by previously processed fragments. If the incoming fragments are not hidden then the appropriate depth values in the depth buffer 112 can be updated to reflect the depth of the incoming fragments. Fragments associated with an opaque object type or a translucent object type are resolved fragments, in the sense that the presence and/or depth values of these fragments will not be altered by the fragment processing module 106. As described below, the “presence” referred to here is presence in the primitive, rather than for example presence in a final image, where other factors, such as occlusion, may apply. Therefore, if the incoming fragments are opaque or translucent then the depth testing logic 110 will use the depth values of incoming fragments (which pass the depth test) to overwrite the depth values in the depth buffer 112. If the incoming fragments are opaque then the overwritten fragments can be discarded since they will not contribute to the final rendered image. However, if the incoming fragments are translucent then the overwritten fragments might still contribute to the final rendered image. Therefore, translucent fragments are processed such that a new translucent fragment value is combined with a previous fragment value using a blending equation that is indicated by the application. Typically the blending equation is implemented in the fragment processing module 106 and uses an alpha value that is sourced from a texture in order to determine how transparent the fragment is, in a process referred to as “alpha blending”.
Other types of objects may include unresolved fragments. Fragment may be “unresolved” if the presence and/or depth values of the fragments may be altered by the fragment processing module 106. For example, fragments generated when a punch through object type arrives at the HSR module 104 are, initially, unresolved fragments because their presence is yet to be resolved by the fragment processing module 106. A primitive with a punch through object type may have holes (i.e. transparent areas) which are determined by texturing and shading operations. A fragment is said to be present in a primitive if it corresponds to an opaque area of the primitive, and not to be present if it corresponds to a transparent area of the primitive. Punch through object types should be processed by the HSR module such that it is possible to see through the holes left after the removal of any fragments that are determined not to be present. If a punch through fragment passes an initial depth test (based on comparing its depth value with the corresponding depth value in the depth buffer 112) then the punch through fragment is forwarded to the fragment processing module 106, but at that point the depth value in the depth buffer 112 is not updated, because the depth buffer 112 is arranged to hold only depth values for resolved fragments (i.e. depth values which will not be altered or invalidated by feedback from the fragment processing module 106) to ensure that the results of the depth tests are accurate. The fragment processing module 106 processes punch through fragments by performing a test (which may be referred to as an “alpha test”) which indicates whether a fragment is “present” i.e. is part of the primitive, or not. In this way, the fragment processing module 106 resolves the presence of the punch through fragments. The alpha test for a fragment uses an alpha value that may be sourced from a texture in order to determine whether the fragment is present or not. The result of this test is fed back to the depth testing logic 110, as shown by the “feedback” in FIG. 1. If a fragment is determined not to be present (i.e. if the fragment fails the alpha test) then no depth value is written to the depth buffer 112 for that fragment. However, if the fragment is determined to be present (i.e. if the fragment passes the alpha test) then the feedback to the depth testing logic 110 indicates that the presence of the fragment has been resolved, such that the fragment may now be treated as a resolved fragment. The depth testing logic 110 can then update the depth buffer 112 with the depth value of the punch through fragment.
FIG. 1 shows that the tag buffer 114 is situated at the interface between the depth testing logic 110 and the fragment processing module 106. Tags are primitive identifiers which associate a fragment with the primitive of which it is a part, and which allow attributes such as texturing and shading data for the primitive to be fetched when required. The tag buffer 114 is used to hold tags for fragments from the front most primitives (e.g. those fragments which pass the depth test) for each sample position in the part of the rendering space currently being processed (e.g. in a tile when the system 100 is a tile-based system). Tags for opaque fragments which pass the depth tests are typically written into the tag buffer 114 even if they overwrite an existing tag as that corresponds to the correct operation to process opaque fragments, as described above. Fragments from translucent and punch through primitives may need to be combined with fragments that they overdraw. The combining of these fragments typically must be performed in the order that they were submitted by the application. As such, whenever translucent or punch through fragments are found to lie in front of fragments currently stored within the tag buffer 114, the HSR module 104 flushes currently visible tags to the fragment processing module 106. As described above, in the case of punch through fragments, the presence of fragments, and hence whether their depth values should be updated in the depth buffer 112, is determined by the fragment processing module 106. Therefore, tags for punch through primitives must also be flushed directly after any tags currently stored within the tag buffer 114 have been flushed. It is noted that the combination of a tag and a position in the tag buffer 114 defines a fragment, so the flushing of tags from the tag buffer 114 can be considered to be flushing fragments from the tag buffer 114. Conceptually, it makes sense to consider fragments being stored in the tag buffer 114 and fragments being flushed out to the fragment processing module 106. In a practical implementation, this conceptual flow of fragments is embodied by storing tags in the tag buffer 114 and flushing tags from the tag buffer 114.
It can be appreciated that in deferred rendering systems, such as system 100, objects with unresolved fragments (e.g. punch through objects) can affect the efficiency of the system. For example, when fragments of a punch through object are encountered the HSR module 104 cannot update the depth buffer 112 with the fragments' depth values until such time as it has received feedback from the fragment processing module 106, i.e. until the presence of the fragments has been resolved. This may have a number of detrimental consequences, such as:                punch through fragments that are subsequently overdrawn by opaque fragments may be unnecessarily shaded by the fragment processing module 106 even though they will not contribute to the final rendered image, hence there is unnecessary processing being performed by the GPU 102;        opaque fragments which follow punch through fragments cannot be processed until the results for the punch through fragments have been returned from the fragment processing module 106 to the HSR module 104, so there may be a stall in the processing while the depth values of the punch through fragments are resolved; and        when the feedback is received at the HSR module 104 from the fragment processing module 106, the depth values for the punch through fragments that have been determined to be present need to be re-calculated so that the depth buffer 112 can be updated correctly.        